﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ShimmerConnect
{
    public partial class Main : Form
    {
        AppSettings pSettingsManager;
        ShimmerProfile pProfile;
        ShimmerApplicationSettings pSettings;
        ShimmerCalibration pCalibration;

        ShimmerDeviceCollection pDeviceCollection;

        //private bool connectToCortex = true;
        //private CortexWrapper cortexInterface;
        private MatlabWrapper matlabInterface;

        private string profileFilePath = "shimmerprofile.xml";
        private string calibrationFilePath = "shimmercalibration.xml";

        public Main()
        {
            // Initialize the GUI
            InitializeComponent();

            btnConnect.Enabled = true;
            btnStartStream.Enabled = false;
            btnStopStream.Enabled = false;
            btnDisconnect.Enabled = false;
            txtComConnected.Enabled = false;

            foreach (string rate in Shimmer.SamplingRatesString)
            {
                cmbSamplingRate.Items.Add(rate);
            }
            foreach (string sensitivity in Shimmer.AccelSensitivityString)
            {
                cmbAccelSensitivity.Items.Add(sensitivity);
            }

            txtSettingsFolder.Enabled = false;

            FormEditState(true);

            // Load SHIMMER profile (or could ask user for it)
            pSettingsManager = new AppSettings(profileFilePath, calibrationFilePath);
            pProfile = pSettingsManager.GetProfile();
            ProfileFormUpdate();

            // Load SHIMMER settings
            pSettings = pSettingsManager.GetSettings();
            SettingFormUpdate();

            // Load SHIMMER calibration (TODO not actually used right now)
            pCalibration = pSettingsManager.GetCalibration();

            // Load MATLAB interface
            // matlabInterface = new MatlabWrapper(pSettings);

            // Interface with the SHIMMER devices
            pDeviceCollection = new ShimmerDeviceCollection(this.components, pProfile, pSettings);
        }

        private void ProfileFormUpdate()
        { 
            // sync the form appearance with pProfile
            SplitSensors(pProfile.GetSensors());
            cmbSamplingRate.SelectedIndex = SamplingRateToList(pProfile.GetAdcSamplingRate());

            cmbAccelSensitivity.SelectedIndex = pProfile.GetAccelSensitivity(); 
        }

        private void SettingFormUpdate()
        {
            txtCsvFolder.Text = pSettings.CSVFilePath;
            txtSettingsFolder.Text = profileFilePath;     
        }

        private int combineSensors()
        {
            int val = 0;

            if (chBxAccel.Checked)
                val |= (int)Shimmer.SensorBitmap.SensorAccel;
            if (chBxGyro.Checked)
                val |= (int)Shimmer.SensorBitmap.SensorGyro;
            if (chBxMag.Checked)
                val |= (int)Shimmer.SensorBitmap.SensorMag;
            if (chBxECG.Checked)
                val |= (int)Shimmer.SensorBitmap.SensorECG;
            if (chBxEMG.Checked)
                val |= (int)Shimmer.SensorBitmap.SensorEMG;
            if (chBxGSR.Checked)
                val |= (int)Shimmer.SensorBitmap.SensorGSR;
            if (chBxAnEx0.Checked)
                val |= (int)Shimmer.SensorBitmap.SensorAnExA0;
            if (chBxAnEx7.Checked)
                val |= (int)Shimmer.SensorBitmap.SensorAnExA7;

            return val;
        }

        private void SplitSensors(int val)
        {
            if ((val & (int)Shimmer.SensorBitmap.SensorAccel) != 0)
            {
                chBxAccel.Checked = true;
                cmbAccelSensitivity.Enabled = true;
            }
            else
            {
                chBxAccel.Checked = false;
                cmbAccelSensitivity.Enabled = false;
            }

            if ((val & (int)Shimmer.SensorBitmap.SensorGyro) != 0)
                chBxGyro.Checked = true;
            else
                chBxGyro.Checked = false;

            if ((val & (int)Shimmer.SensorBitmap.SensorMag) != 0)
                chBxMag.Checked = true;
            else
                chBxMag.Checked = false;

            if ((val & (int)Shimmer.SensorBitmap.SensorECG) != 0)
                chBxECG.Checked = true;
            else
                chBxECG.Checked = false;

            if ((val & (int)Shimmer.SensorBitmap.SensorEMG) != 0)
                chBxEMG.Checked = true;
            else
                chBxEMG.Checked = false;

            if ((val & (int)Shimmer.SensorBitmap.SensorGSR) != 0)
                chBxGSR.Checked = true;
            else
                chBxGSR.Checked = false;

            if ((val & (int)Shimmer.SensorBitmap.SensorAnExA0) != 0)
                chBxAnEx0.Checked = true;
            else
                chBxAnEx0.Checked = false;

            if ((val & (int)Shimmer.SensorBitmap.SensorAnExA7) != 0)
                chBxAnEx7.Checked = true;
            else
                chBxAnEx7.Checked = false;
        }

        private int SamplingRateToList(int val)
        {
            int ret;

            switch (val)
            {
                case (int)Shimmer.SamplingRates.Sampling0HzOff:
                    ret = 0;
                    break;
                case (int)Shimmer.SamplingRates.Sampling10Hz:
                    ret = 1;
                    break;
                case (int)Shimmer.SamplingRates.Sampling50Hz:
                    ret = 2;
                    break;
                case (int)Shimmer.SamplingRates.Sampling100Hz:
                    ret = 3;
                    break;
                case (int)Shimmer.SamplingRates.Sampling125Hz:
                    ret = 4;
                    break;
                case (int)Shimmer.SamplingRates.Sampling166Hz:
                    ret = 5;
                    break;
                case (int)Shimmer.SamplingRates.Sampling200Hz:
                    ret = 6;
                    break;
                case (int)Shimmer.SamplingRates.Sampling250Hz:
                    ret = 7;
                    break;
                case (int)Shimmer.SamplingRates.Sampling500Hz:
                    ret = 8;
                    break;
                case (int)Shimmer.SamplingRates.Sampling1000Hz:
                    ret = 9;
                    break;
                default:
                    ret = -1;
                    break;
            }
            return ret;
        }

        // ----------------------------------------------------------------------------------------------------
        // Form Interaction

        private void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                // connect to the SHIMMER devices
                pDeviceCollection.OpenAndConnect();
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message, Shimmer.ApplicationName,
                    MessageBoxButtons.OK, MessageBoxIcon.Warning);

                pDeviceCollection.CloseVariable();
            }

            btnConnect.Enabled = false;
            btnStartStream.Enabled = true;
            btnStopStream.Enabled = false;
            btnDisconnect.Enabled = true;

            txtComConnected.Text = pDeviceCollection.ToString();

            FormEditState(false);
        }

        private void btnStartStream_Click(object sender, EventArgs e)
        {
            if (pDeviceCollection.GetConnectionStatus())
            {
                // if the system is connected...
                pDeviceCollection.DataStreamStart();
            }
            else
            {
                MessageBox.Show("No serial port is open", Shimmer.ApplicationName,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            btnConnect.Enabled = false;
            btnStartStream.Enabled = false;
            btnStopStream.Enabled = true;
            btnDisconnect.Enabled = false;

            FormEditState(false);
        }

        private void btnStopStream_Click(object sender, EventArgs e)
        {
            pDeviceCollection.DataStreamStop();

            btnConnect.Enabled = false;
            btnStartStream.Enabled = true;
            btnStopStream.Enabled = false;
            btnDisconnect.Enabled = true;

            FormEditState(false);
        }

        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            pDeviceCollection.Disconnect();

            btnConnect.Enabled = true;
            btnStartStream.Enabled = false;
            btnStopStream.Enabled = false;
            btnDisconnect.Enabled = false;

            txtComConnected.Text = "";

            FormEditState(true);
        }

        private void btnSetProfile_Click(object sender, EventArgs e)
        {
            // check sampling rate
            if (SamplingRateToList(pProfile.GetAdcSamplingRate()) != cmbSamplingRate.SelectedIndex)
            {
                pProfile.SetAdcSamplingRate(ListToSamplingRate(cmbSamplingRate.SelectedIndex));
                pProfile.changeSamplingRate = true;
            }

            // check sensors
            if (combineSensors() != pProfile.GetSensors())
            {
                pProfile.setSensors(combineSensors());
                pProfile.changeSensors = true;
            }

            // check 5V reg
            if (chBx5VReg.Checked != pProfile.GetVReg())
            {
                pProfile.SetVReg(chBx5VReg.Checked);
                pProfile.change5Vreg = true;
            }
                
            // check Power MUX
            if (chBxPwrMux.Checked != pProfile.GetPMux())
            {
                pProfile.SetPMux(chBxPwrMux.Checked);
                pProfile.changePwrMux = true;
            }

            // check accel sensitivity
            if (cmbAccelSensitivity.SelectedIndex != pProfile.GetAccelSensitivity())
            {
                pProfile.SetAccelSensitivity(cmbAccelSensitivity.SelectedIndex);
                pProfile.changeAccelSens = true;
            }

            // new csv file path
            string csvFilePath = txtCsvFolder.Text.ToString();
            pSettings.SetCsvPath(csvFilePath);

            // save it to file
            pSettingsManager.UpdateAppSettings(pProfile, csvFilePath);

            // reinitalize the shimmer device collections with new settings
            pDeviceCollection = new ShimmerDeviceCollection(this.components, pProfile, pSettings);
        }

        private int ListToSamplingRate(int val)
        {
            int ret;

            switch (val)
            {
                case 0:
                    ret = (int)Shimmer.SamplingRates.Sampling0HzOff;
                    break;
                case 1:
                    ret = (int)Shimmer.SamplingRates.Sampling10Hz;
                    break;
                case 2:
                    ret = (int)Shimmer.SamplingRates.Sampling50Hz;
                    break;
                case 3:
                    ret = (int)Shimmer.SamplingRates.Sampling100Hz;
                    break;
                case 4:
                    ret = (int)Shimmer.SamplingRates.Sampling125Hz;
                    break;
                case 5:
                    ret = (int)Shimmer.SamplingRates.Sampling166Hz;
                    break;
                case 6:
                    ret = (int)Shimmer.SamplingRates.Sampling200Hz;
                    break;
                case 7:
                    ret = (int)Shimmer.SamplingRates.Sampling250Hz;
                    break;
                case 8:
                    ret = (int)Shimmer.SamplingRates.Sampling500Hz;
                    break;
                case 9:
                    ret = (int)Shimmer.SamplingRates.Sampling1000Hz;
                    break;
                default:
                    ret = -1;
                    break;
            }
            return ret;
        }

        private void FormEditState(bool status)
        {
            cmbSamplingRate.Enabled = status;

            chBxAccel.Enabled = status;
            chBxGyro.Enabled = status;
            chBxMag.Enabled = status;

            btnSetProfile.Enabled = status;

            status = false;
            cmbAccelSensitivity.Enabled = status;
            chBxECG.Enabled = status;
            chBxEMG.Enabled = status;
            chBxGSR.Enabled = status;
            chBxAnEx0.Enabled = status;
            chBxAnEx7.Enabled = status;
            chBx5VReg.Enabled = status;
            chBxPwrMux.Enabled = status;            
        }

        // ----------------------------------------------------------------------------------------------------
        // MotionAnalysis (Cortex) Interfacing

        //public void CortexInitalize()
        //{
        //    if (connectToCortex)
        //    {
        //        cortexInterface = new CortexWrapper();

        //        cortexInterface.CortexInitalize();
        //    }

        //}

        //public void CortexRecordingStart()
        //{
        //    cortexInterface.CortexRecordingStart();

        //}

        //public void CortexRecordingStop()
        //{
        //    cortexInterface.CortexRecordingStop();
        //}

        // ----------------------------------------------------------------------------------------------------
        // MathWorks (MATLAB) Interfacing
        //public void MatlabInitalize()
        //{
        //    matlabInterface = new MatlabWrapper();
        //    MatlabTestSeq();
        //    matlabInterface.CloseVariable();
        //}

        //public void MatlabTestSeq()
        //{
        //    //MessageBox.Show(matlabInterface.Execute("magic(4)"));

        //    int[] dataMtx = new int[5] { 1, 2, 3, 4, 5 };
        //    int[,] myArray = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };

        //    matlabInterface.PutWorkspaceData("foo", "base", dataMtx);
        //    matlabInterface.PutWorkspaceData("foo2", "base", myArray);
        //    matlabInterface.PutWorkspaceData("bar", "base", "tiger");
        //}
        
        
    } // end Main()
}
